﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Xml.Linq;
using NetSurveillance.WebApp.Models;

namespace NetSurveillance.WebApp.Utilities
{
    public class SupportUtility
    {
        private static readonly IDictionary<string, IList<SupportProtocol>> ProtocolsDic =
            new Dictionary<string, IList<SupportProtocol>>();

        private readonly static IDictionary<string, IList<SupportField>> DisplayFieldsDic =
            new Dictionary<string, IList<SupportField>>();

        private static readonly IDictionary<string, IList<SupportField>> ExportFieldsDic =
            new Dictionary<string, IList<SupportField>>();

        public static void LoadSupportData(string filePath, string fileName)
        {
            var fileDic = new DirectoryInfo(filePath);
            var supportFile = fileDic.GetFiles(fileName + ".xml").FirstOrDefault();
            if (supportFile == null) return;
            LoadProtocols(supportFile.FullName);
            LoadFields(supportFile.FullName);
        }

        public static IList<SupportField> GetDisplayField()
        {
            string currentLang = Thread.CurrentThread.CurrentUICulture.Name.ToLower();
            if (!DisplayFieldsDic.ContainsKey(currentLang))
                currentLang = PresetValues.DefaultLang.ToLower();
            return DisplayFieldsDic.ContainsKey(currentLang)
                       ? DisplayFieldsDic[currentLang]
                       : new List<SupportField>();
        }

        public static IList<SupportField> GetAllField()
        {
            return GetDisplayField().Concat(GetExportField()).ToList();
        }

        public static IList<SupportField> GetExportField()
        {
            string currentLang = Thread.CurrentThread.CurrentUICulture.Name.ToLower();
            if (!ExportFieldsDic.ContainsKey(currentLang))
                currentLang = PresetValues.DefaultLang.ToLower();
            return ExportFieldsDic.ContainsKey(currentLang)
                       ? ExportFieldsDic[currentLang]
                       : new List<SupportField>();
        } 

        public static IList<SupportProtocol> GetSupportProtocols()
        {
            string currentLang = Thread.CurrentThread.CurrentUICulture.Name.ToLower();
            if (!ProtocolsDic.ContainsKey(currentLang))
                currentLang = PresetValues.DefaultLang.ToLower();
            return ProtocolsDic.ContainsKey(currentLang)
                       ? ProtocolsDic[currentLang]
                       : new List<SupportProtocol>();
        }

        private static void LoadProtocols(string fullPath)
        {
            var resourceElement = XElement.Load(fullPath);
            if (resourceElement.IsEmpty) return;
            var protolsEles = resourceElement.Elements("Protocols");
            foreach (var protolsEle in protolsEles)
            {
                if (protolsEle.IsEmpty) continue;
                var langAttr = protolsEle.Attribute("lang");
                string langStr = ((langAttr == null || string.IsNullOrWhiteSpace(langAttr.Value))
                                     ? PresetValues.DefaultLang
                                     : langAttr.Value).ToLower();
                if (!ProtocolsDic.ContainsKey(langStr))
                    ProtocolsDic[langStr] = new List<SupportProtocol>();
                foreach (var protocolEle in protolsEle.Elements("Protocol"))
                {
                    var nameAttr = protocolEle.Attribute("Name");
                    var displayAttr = protocolEle.Attribute("DisplayText");
                    var isImAttr = protocolEle.Attribute("IsIM");
                    if (nameAttr == null || string.IsNullOrWhiteSpace(nameAttr.Value)) continue;
                    string displayText = (displayAttr == null || string.IsNullOrWhiteSpace(displayAttr.Value))
                                             ? nameAttr.Value
                                             : displayAttr.Value;
                    bool isIM = false;
                    if (isImAttr != null && !string.IsNullOrEmpty(isImAttr.Value))
                        bool.TryParse(isImAttr.Value, out isIM);
                    var sptPrtc = new SupportProtocol
                        {
                            Name = nameAttr.Value,
                            DisplayText = displayText,
                            IsIM = isIM,
                            SupportFields = new List<SupportField>()
                        };
                    var fieldEles = protocolEle.Element("Fields");
                    if (fieldEles != null && !fieldEles.IsEmpty)
                    {
                        foreach (var fieldEle in fieldEles.Elements("Field"))
                        {
                            sptPrtc.SupportFields.Add(ReadSupportField(fieldEle, "ActionName"));
                        }
                    }
                    ProtocolsDic[langStr].Add(sptPrtc);
                }
            }
        }

        private static void LoadFields(string fullPath)
        {
            var resourceElement = XElement.Load(fullPath);
            if (resourceElement.IsEmpty) return;
            var fieldEles = resourceElement.Elements("DisplayFields");
            foreach (var fieldRootEle in fieldEles)
            {
                if (fieldRootEle.IsEmpty) continue;
                var langAttr = fieldRootEle.Attribute("lang");
                if (langAttr == null || string.IsNullOrWhiteSpace(langAttr.Value)) continue;
                string langStr = langAttr.Value.ToLower();
                if (!DisplayFieldsDic.ContainsKey(langStr))
                    DisplayFieldsDic[langStr] = new List<SupportField>();
                if (!ExportFieldsDic.ContainsKey(langStr))
                    ExportFieldsDic[langStr] = new List<SupportField>();
                foreach (var fieldEle in fieldRootEle.Elements("Field"))
                {
                    var sptField = ReadSupportField(fieldEle);
                    switch (sptField.FieldType)
                    {
                        case "Both":
                            DisplayFieldsDic[langStr].Add(sptField);
                            ExportFieldsDic[langStr].Add(sptField);
                            break;
                        case "Display":
                            DisplayFieldsDic[langStr].Add(sptField);
                            break;
                        case "Export":
                            ExportFieldsDic[langStr].Add(sptField);
                            break;
                    }
                }
            }
        }

        private static SupportField ReadSupportField(XElement fieldEle, string keyName = "PropertyName")
        {
            var nameAttr = fieldEle.Attribute(keyName);
            if (nameAttr == null || string.IsNullOrWhiteSpace(nameAttr.Value))
                throw new Exception(
                    string.Format(
                        "The KeyName:{0} can't be found in Field Element or it's value is null or empty.",
                        keyName));
            var displayAttr = fieldEle.Attribute("DisplayText");
            string fieldDisplayStr = (displayAttr == null ||
                                      string.IsNullOrWhiteSpace(displayAttr.Value))
                                         ? nameAttr.Value
                                         : displayAttr.Value;
            var fieldTypeAttr = fieldEle.Attribute("FieldType");
            string fieldType = fieldTypeAttr != null &&
                               !string.IsNullOrWhiteSpace(fieldTypeAttr.Value)
                                   ? fieldTypeAttr.Value
                                   : null;
            var sptField = keyName == "PropertyName"
                               ? new SupportField { PropertyName = nameAttr.Value, DisplayText = fieldDisplayStr }
                               : new SupportField { ActionName = nameAttr.Value, DisplayText = fieldDisplayStr };
            if (!string.IsNullOrWhiteSpace(fieldType))
                sptField.FieldType = fieldType;
            return sptField;
        }
    }
}